home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
344_01
/
mtx.doc
< prev
next >
Wrap
Text File
|
1990-12-30
|
4KB
|
90 lines
RUN-TIME ARRAYS IN C
Dynamic Allocation and Usage of Array
Structures Composed during Run-Time Operations
Bill Forseth, Duluth MN
One of the problems frequently faced by programmers is the fact that
array allocation is a compile-time operation. If the size of an array is
unknown during the compilation process one usually needs to implement some
form of linked list, with all the attendant overhead and occasionally
debugging grief.
This need not be so. Conceptually, an array is a group of like items,
(or records), with individual elements made available through sub-
scripting. An array can be passed as a pointer, (which in fact it is),
which can lead to speedy operations. Arrays need not be traversed, nor do
they have to be freed. An array element contains only the space needed to
hold the specified value(s), no pointers to next, last, head, tail, etc.
nodes.
These basic problems need to be overcome in creating run-time arrays:
1. declaring the basic element type
2. allocation for the array as a whole
3. element accessing
The solution for the first problem, 99 out of a hundred times, is simple
enough - hard-code the type, perhaps in a header file. For that hundredth
time, (which we needn't get into for the purposes of this article), C's
invaluable "sizeof" operator can be used.
For the second problem, an example would be more instructive than my
words. Given that the type is float, and the need is for an array of N
elements, (where the value of N is determined, like any other variable, at
run-time). An array called 'A' can be created with this simple operation:
A = (float)malloc(sizeof(float)*N);
(Note that A should be declared as a POINTER to a float in it's own
declaration).
Now A points to a memory location containing the number of bytes (in the
system definition of a float) times N, which is our original working
definition of an array's memory space.
Number three says we need to solve the element accessibility problem,
which given C's pointer arithmetic, is efficient and relatively painless.
To access the i-th element of array A, all we need to do is use this simple
formula:
*(A + i)
The compiler already knows that A is a float pointer, so *(A + 0) will
access the first element. *(A + 1) will access the second, and so on.
So far, so good. Now what about multi-dimensional arrays? The theory is
the same, although the implementation may be a bit more complex.
Problem one stays the same. Problem two demands only one more operation
in the allocation phase. Say one needed an N by M array. The allocation
could look like this:
A=(float)malloc(sizeof(float) * N * M);
Now the sticky part - not too bad, yet easy enough to mis-calculate,
(especially in a computation-heavy program). The solution to number three
in this case is two fold. First, say we want to access the element normally
associated in array operations as A[i][j]. For our purposes this becomes:
*(A + (N * i) + j);
Which still doesn't look too bad - until you get a group on the left or
right hand side of an operation. For that reason, I usually use a macro
defined as the above. Or more specifically:
#define A_(N,i,j) *(A+(N*i)+j)
If 'N' is a variable globally accessible to all procedures needing to
access elements, then the #define could be identified as simply:
#define A_(i,j) . . .
Which is much easier to read, and hence debug, than *(A+(N*i)+j).
The same type of operations can be defined for multi-dimension arrays
bigger that two, (although the memory does tend to get a bit stretched with
these).